package com.backend.utils;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.TextUtils;

/**
 * @author HUJIAMIN
 * @since 2019/5/28
 */
public class HttpUtil {


  private HttpUtil() {
  }

  private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
  private static final String CHARSET_NAME = "UTF-8";
  private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
  private static final OkHttpClient HTTP_CLIENT;

  static {
    HTTP_CLIENT = new OkHttpClient().newBuilder()
      .connectTimeout(10, TimeUnit.SECONDS)
      .writeTimeout(10, TimeUnit.SECONDS)
      .readTimeout(20, TimeUnit.SECONDS)
      .build();
  }

  /**
   * 同步get
   */
  public static String get(String url) throws Exception {
    Request request = new Request.Builder().url(url).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步get请求
   */
  public static String get(String url, Map<String, String> data) throws Exception {
    url = getRequestUrl(url, data);
    Request request = new Request.Builder().url(url).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步get headers数据
   */
  public static String get(String url, String headerName, String headerValue) throws IOException {
    Request request = new Request.Builder().url(url).addHeader(headerName, headerValue).get()
      .build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步get请求
   *
   * @param url         请求地址
   * @param data        请求参数
   * @param headerName  请求头name
   * @param headerValue 请求头value
   * @return response
   */
  public static String get(String url, Map<String, String> data, String headerName,
    String headerValue) throws Exception {
    url = getRequestUrl(url, data);
    Request request = new Request.Builder().url(url).header(headerName, headerValue).build();

    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步get headers数据
   */
  public static String getWithHeaders(String url, Map<String, String> headers) throws IOException {
    Request request = new Request.Builder().url(url).headers(Headers.of(headers)).get().build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 异步get请求
   */
  public static void get(String url, Callback responseCallback) {
    Request request = new Request.Builder().url(url).build();
    enqueue(request, responseCallback);
  }

  /**
   * 异步get
   */
  public static void get(String url, Map<String, String> data, Callback responseCallback) {
    url = getRequestUrl(url, data);
    Request request = new Request.Builder().url(url).build();
    enqueue(request, responseCallback);
  }

  /**
   * 同步post json数据
   */
  public static String post(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).post(body).build();

    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * post请求带请求头
   *
   * @param url     请求地址
   * @param json    请求体
   * @param headers 请求头
   * @return string
   */
  public static String post(String url, String json, Map<String, String> headers)
    throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Headers headerBuild = Headers.of(headers);
    Request request = new Request.Builder().url(url).headers(headerBuild).post(body).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步post json数据
   */
  public static String post(String url, String json, String headerName, String headerValue)
    throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).addHeader(headerName, headerValue).post(body)
      .build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步post 键值对数据
   */
  public static String post(String url, Map<String, String> data) throws IOException {
    FormBody.Builder builder = new FormBody.Builder();
    RequestBody body = createRequestBody(data);
    Request request = new Request.Builder().url(url).post(body).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 异步post json
   */
  public static void post(String url, String json, Callback responseCallback) {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).post(body).build();
    enqueue(request, responseCallback);
  }

  /**
   * 异步post key-value
   */
  public static void post(String url, Map<String, String> data, Callback responseCallback) {
    RequestBody body = createRequestBody(data);
    Request request = new Request.Builder().url(url).post(body).build();
    enqueue(request, responseCallback);
  }

  /**
   * 同步put
   */
  public static String put(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).put(body).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 同步put key-value
   */
  public static String put(String url, Map<String, String> data) throws IOException {
    RequestBody body = createRequestBody(data);
    Request request = new Request.Builder().url(url).put(body).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 异步put json
   */
  public static void put(String url, String json, Callback responseCallback) {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).put(body).build();
    enqueue(request, responseCallback);
  }

  /**
   * 异步put key-value
   */
  public static void put(String url, Map<String, String> data, Callback responseCallback) {
    RequestBody body = createRequestBody(data);
    Request request = new Request.Builder().url(url).put(body).build();
    enqueue(request, responseCallback);
  }

  /**
   * post的请求参数，构造RequestBody
   *
   * @param bodyParams 请求参数
   * @return RequestBody
   */
  private static RequestBody createRequestBody(Map<String, String> bodyParams) {
    FormBody.Builder builder = new FormBody.Builder();
    for (String key : bodyParams.keySet()) {
      builder.add(key, bodyParams.get(key));
    }
    return builder.build();
  }

  /**
   * 通用同步请求。
   */
  public static Response execute(Request request) throws IOException {
    return HTTP_CLIENT.newCall(request).execute();
  }

  /**
   * 通用异步请求
   */
  public static void enqueue(Request request, Callback responseCallback) {
    HTTP_CLIENT.newCall(request).enqueue(responseCallback);
  }

  public static String getStringFromServer(String url) throws IOException {
    Request request = new Request.Builder().url(url).build();
    Response response = execute(request);
    if (response.isSuccessful()) {
      return response.body().string();
    } else {
      throw new IOException("Unexpected code " + response);
    }
  }

  /**
   * 这里使用了HttpClinet的API。只是为了方便
   */
  public static String formatParams(List<BasicNameValuePair> params) {
    return URLEncodedUtils.format(params, CHARSET_NAME);
  }

  /**
   * 为HttpGet 的 url 方便的添加多个name value 参数。
   */
  public static String attachHttpGetParams(String url, List<BasicNameValuePair> params) {
    return url + "?" + formatParams(params);
  }

  /**
   * 为HttpGet 的 url 方便的添加1个name value 参数。
   */
  public static String attachHttpGetParam(String url, String name, String value) {
    return url + "?" + name + "=" + value;
  }

  /**
   * get方式URL拼接
   */
  private static String getRequestUrl(String url, Map<String, String> map) {
    if (map == null || map.size() == 0) {
      return url;
    } else {
      StringBuilder newUrl = new StringBuilder(url);
      if (!url.contains("?")) {
        newUrl.append("?rd=").append(Math.random());
      }
      for (Map.Entry<String, String> item : map.entrySet()) {
        if (!TextUtils.isEmpty(item.getKey().trim())) {
          try {
            newUrl.append("&").append(item.getKey().trim()).append("=")
              .append(URLEncoder.encode(item.getValue().trim(), "UTF-8"));
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
      return newUrl.toString();
    }
  }

}
